package online.dgyj.linkcontrol;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import com.nle.mylibrary.claimer.connector.ConnectorListener;
import com.nle.mylibrary.databus.DataBusFactory;
import com.nle.mylibrary.device.GenericConnector;
import com.nle.mylibrary.device.listener.ConnectResultListener;

import java.util.concurrent.TimeUnit;

@SuppressLint("SetTextI18n")
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Handler handler;
    private GenericConnector genericConnector;
    private String ip;
    private int port, address;
    private final Thread getSensorThread = getLinkIn();

    private final int[] DOVal = new int[4];
    private final int[] INVal = new int[4];

    private TextView sensor1Text, sensor2Text, sensor3Text, sensor4Text, sensor5Text, sensor6Text, sensor7Text, sensor8Text;
    private TextView sensor1Value, sensor2Value, sensor3Value, sensor4Value, sensor5Value, sensor6Value, sensor7Value, sensor8Value;
    private ConstraintLayout sensor1, sensor2, sensor3, sensor4;
    private EditText IPEdit, PortEdit, AddressEdit;
    private Switch RTUSwitch;
    private Button LinkBtn, AllOnBtn, AllOffBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

        bind();
    }

    /**
     * 初始化视图
     * 此方法主要适配通用UI,正常不推荐
     */
    private void InitView() {
        sensor1Text.setText("DO1");
        sensor2Text.setText("DO2");
        sensor3Text.setText("DO3");
        sensor4Text.setText("DO4");
        sensor5Text.setText("IN1");
        sensor6Text.setText("IN2");
        sensor7Text.setText("IN3");
        sensor8Text.setText("IN4");
    }

    /**
     * 实例化控件
     */
    private void bind() {

        handler = new Handler(Looper.getMainLooper());

        sensor1Text = findViewById(R.id.sensor1Text);
        sensor2Text = findViewById(R.id.sensor2Text);
        sensor3Text = findViewById(R.id.sensor3Text);
        sensor4Text = findViewById(R.id.sensor4Text);
        sensor5Text = findViewById(R.id.sensor5Text);
        sensor6Text = findViewById(R.id.sensor6Text);
        sensor7Text = findViewById(R.id.sensor7Text);
        sensor8Text = findViewById(R.id.sensor8Text);

        sensor1Value = findViewById(R.id.sensor1Value);
        sensor2Value = findViewById(R.id.sensor2Value);
        sensor3Value = findViewById(R.id.sensor3Value);
        sensor4Value = findViewById(R.id.sensor4Value);
        sensor5Value = findViewById(R.id.sensor5Value);
        sensor6Value = findViewById(R.id.sensor6Value);
        sensor7Value = findViewById(R.id.sensor7Value);
        sensor8Value = findViewById(R.id.sensor8Value);

        sensor1 = findViewById(R.id.sensor1);
        sensor2 = findViewById(R.id.sensor2);
        sensor3 = findViewById(R.id.sensor3);
        sensor4 = findViewById(R.id.sensor4);

        IPEdit = findViewById(R.id.IPEdit);
        PortEdit = findViewById(R.id.PortEdit);
        AddressEdit = findViewById(R.id.AddressEdit);

        RTUSwitch = findViewById(R.id.RTUSwitch);

        LinkBtn = findViewById(R.id.LinkBtn);
        AllOnBtn = findViewById(R.id.AllOnBtn);
        AllOffBtn = findViewById(R.id.AllOffBtn);

        InitView();

        // 事件处理
        LinkBtn.setOnClickListener(this);
        AllOnBtn.setOnClickListener(this);
        AllOffBtn.setOnClickListener(this);
        sensor1.setOnClickListener(this);
        sensor2.setOnClickListener(this);
        sensor3.setOnClickListener(this);
        sensor4.setOnClickListener(this);

        RTUSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // 事件处理
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    IPEdit.setHint("SerialName");
                    PortEdit.setHint("Baud");
                    IPEdit.setText("");
                    PortEdit.setText("");
                } else {
                    IPEdit.setHint("IP");
                    PortEdit.setHint("Port");
                    IPEdit.setText("");
                    PortEdit.setText("");
                }
            }
        });
    }

    private int tag = 0;    // 用于保证线程按顺序单线程运行

    /**
     * 读取DO数值
     *
     * @return 线程
     */
    private Thread getLinkDo() {
        return new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    for (int i = 0; i < 4; i++) {
                        final int count = i;
                        genericConnector.sendSearchLinkOut(address, i, new ConnectorListener() {
                            @Override
                            public void onSuccess(boolean b) {
                                DOVal[count] = genericConnector.getSearchLinkOutIn();
                                tag = count + 1;
                            }

                            @Override
                            public void onFail(Exception e) {

                            }
                        });
                        while (tag == i) {
                            TimeUnit.MILLISECONDS.sleep(100);
                        }
                    }
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            sensor1Value.setText(String.valueOf(DOVal[0]));
                            sensor2Value.setText(String.valueOf(DOVal[1]));
                            sensor3Value.setText(String.valueOf(DOVal[2]));
                            sensor4Value.setText(String.valueOf(DOVal[3]));
                        }
                    });
                    tag = 0;
                    TimeUnit.MILLISECONDS.sleep(200);
                    getSensorThread.start();
                } catch (Exception e) {
                    Log.e("Get DOVal", e.toString());
                }
            }
        });
    }

    /**
     * 读取IN数据
     *
     * @return 线程
     */
    private Thread getLinkIn() {
        return new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) {
                    try {
                        for (int i = 0; i < 4; i++) {
                            final int count = i;
                            genericConnector.sendLinkReadIn(address, i, new ConnectorListener() {
                                @Override
                                public void onSuccess(boolean b) {
                                    INVal[count] = genericConnector.getSearchLinkOutIn();
                                    tag = count + 1;
                                }

                                @Override
                                public void onFail(Exception e) {

                                }
                            });
                            while (tag == i) {
                                TimeUnit.MILLISECONDS.sleep(80);
                            }
                        }
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                sensor5Value.setText(String.valueOf(INVal[0]));
                                sensor6Value.setText(String.valueOf(INVal[1]));
                                sensor7Value.setText(String.valueOf(INVal[2]));
                                sensor8Value.setText(String.valueOf(INVal[3]));
                            }
                        });
                        tag = 0;
                        TimeUnit.MILLISECONDS.sleep(800);
                    } catch (InterruptedException e) {
                        break;
                    } catch (Exception e) {
                        Log.e("Get INVal", e.toString());
                    }
                }
            }
        });
    }

    /**
     * 控制DO口
     *
     * @param count  通道
     * @param isOpen 数值 true/false
     */
    private void setLinkDo(int count, boolean isOpen) {
        try {
            genericConnector.sendLinkControlOut(address, count, isOpen, new ConnectorListener() {
                @Override
                public void onSuccess(boolean b) {
                    if (isOpen)
                        DOVal[count] = 1;
                    else
                        DOVal[count] = 0;
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            sensor1Value.setText(String.valueOf(DOVal[0]));
                            sensor2Value.setText(String.valueOf(DOVal[1]));
                            sensor3Value.setText(String.valueOf(DOVal[2]));
                            sensor4Value.setText(String.valueOf(DOVal[3]));
                        }
                    });
                }

                @Override
                public void onFail(Exception e) {

                }
            });
        } catch (Exception e) {
            Log.e("Set Do", e.toString());
        }
    }

    /**
     * 控制DO全开/全关
     *
     * @param isOpen true/false
     */
    private void setAllDo(boolean isOpen) {
        try {
            genericConnector.sendLinkAllOnOff(address, isOpen, new ConnectorListener() {
                @Override
                public void onSuccess(boolean b) {
                    for (int i = 0; i < DOVal.length; i++) {
                        if (isOpen)
                            DOVal[i] = 1;
                        else
                            DOVal[i] = 0;
                    }
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            sensor1Value.setText(String.valueOf(DOVal[0]));
                            sensor2Value.setText(String.valueOf(DOVal[1]));
                            sensor3Value.setText(String.valueOf(DOVal[2]));
                            sensor4Value.setText(String.valueOf(DOVal[3]));
                        }
                    });
                }

                @Override
                public void onFail(Exception e) {

                }
            });
        } catch (Exception e) {
            Log.e("Set All Do", e.toString());
        }
    }

    @Override
    public void onClick(View v) {
        // 连接
        if (v.getId() == R.id.LinkBtn) {
            if (genericConnector == null) {
                ip = IPEdit.getText().toString();
                port = Integer.parseInt(PortEdit.getText().toString());
                address = Integer.parseInt(AddressEdit.getText().toString());
                if (RTUSwitch.isChecked()) {
                    Log.i("Start", "Start");
                    genericConnector = new GenericConnector(DataBusFactory.newSerialDataBus(Integer.parseInt(ip), port), new ConnectResultListener() {
                        @Override
                        public void onConnectResult(boolean b) {
                            if (b) {
                                Log.i("Rtu Status", "Link OK");
                                handler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        IPEdit.setEnabled(false);
                                        PortEdit.setEnabled(false);
                                        AddressEdit.setEnabled(false);
                                        RTUSwitch.setEnabled(false);
                                        LinkBtn.setText("DISC");
                                        Toast.makeText(getApplication(), "连接成功", Toast.LENGTH_SHORT).show();
                                    }
                                });
                                getLinkDo().start();
                            } else {
                                Log.e("Rtu Status", "Link Error");
                                genericConnector = null;// 销毁
                                handler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        Toast.makeText(getApplicationContext(), "连接失败", Toast.LENGTH_SHORT).show();
                                    }
                                });
                            }
                        }
                    });
                } else {
                    genericConnector = new GenericConnector(DataBusFactory.newSocketDataBus(ip, port), new ConnectResultListener() {
                        @Override
                        public void onConnectResult(boolean b) {
                            if (b) {
                                Log.i("tcp Status", "Link OK");
                                handler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        IPEdit.setEnabled(false);
                                        PortEdit.setEnabled(false);
                                        AddressEdit.setEnabled(false);
                                        RTUSwitch.setEnabled(false);
                                        LinkBtn.setText("DISC");
                                        Toast.makeText(getApplication(), "连接成功", Toast.LENGTH_SHORT).show();
                                    }
                                });
                                getLinkDo().start();
                            } else {
                                Log.e("tcp Status", "Link Error");
                                genericConnector = null;// 销毁
                                handler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        Toast.makeText(getApplicationContext(), "连接失败", Toast.LENGTH_SHORT).show();
                                    }
                                });
                            }
                        }
                    });
                }
            } else {
                getSensorThread.interrupt();

                IPEdit.setEnabled(true);
                RTUSwitch.setEnabled(true);
                PortEdit.setEnabled(true);
                AddressEdit.setEnabled(true);
                RTUSwitch.setEnabled(true);

                LinkBtn.setText("Link");

                Toast.makeText(getApplication(), "断开连接", Toast.LENGTH_SHORT).show();

                // 销毁
                genericConnector.stopConnect();
                genericConnector = null;
            }
        }
        // DO1开关
        else if (v.getId() == R.id.sensor1) {
            if (DOVal[0] == 0)
                setLinkDo(0, true);
            else if (DOVal[0] == 1)
                setLinkDo(0, false);
        }
        // DO2开关
        else if (v.getId() == R.id.sensor2) {
            if (DOVal[1] == 0)
                setLinkDo(1, true);
            else if (DOVal[1] == 1)
                setLinkDo(1, false);
        }
        // DO3开关
        else if (v.getId() == R.id.sensor3) {
            if (DOVal[2] == 0)
                setLinkDo(2, true);
            else if (DOVal[2] == 1)
                setLinkDo(2, false);
        }
        // DO4开关
        else if (v.getId() == R.id.sensor4) {
            if (DOVal[3] == 0)
                setLinkDo(3, true);
            else if (DOVal[3] == 1)
                setLinkDo(3, false);
        }
        // DO全开
        else if (v.getId() == R.id.AllOnBtn) {
            setAllDo(true);
        }
        // DO全关
        else if (v.getId() == R.id.AllOffBtn) {
            setAllDo(false);
        }
    }
}